package com.jinyijia.api.rest.v1.cart;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jinyijia.api.infrastructure.UserInfoManager;
import com.jinyijia.api.rest.v1.goods.vo.FreightVo;
import com.jinyijia.api.rest.v1.shippingaddress.ShippingAddress;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yangrd
 * @date 2018/8/8
 **/
@RestController
@RequestMapping("carts")
public class CartController {

    private RestTemplate restTemplate;

    @Autowired
    public CartController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @GetMapping
    public List<CartVO> listCurrentUserCart() {
        Integer currentUserId = UserInfoManager.getCurrentUserId();
        JSONArray jsonArray = restTemplate.getForObject("http://goods-service/carts?userId=" + currentUserId, JSONArray.class);
        return jsonArray.stream()
                .map(this::toCommodityVO)
                .collect(Collectors.groupingBy(CommodityVO::getShopId)).entrySet().stream()
                .map(this::toCartVO)
                .collect(Collectors.toList());
    }

    @GetMapping("/count-goods-num")
    public Integer countGoodsNum() {
        Integer userId = UserInfoManager.getCurrentUserId();
        return restTemplate.getForObject("http://goods-service/carts/count-goods-num?userId={1}", Integer.class, userId);
    }

    @PostMapping
    public void add(@RequestBody CartRequest request) {
        Integer userId = UserInfoManager.getCurrentUserId();
        CartDTO dto = new CartDTO(userId, request.getShopId(), request.getSkuCode(), request.getNumber(), request.getSkuId(), request.getGoodsId());
        restTemplate.postForEntity("http://goods-service/carts", dto, Object.class);
    }

    @DeleteMapping
    public void delete(Integer shopId, String skuCode) {
        Integer userId = UserInfoManager.getCurrentUserId();
        restTemplate.delete("http://goods-service/carts?userId={1}&shopId={2}&skuCode={3}", userId, shopId, skuCode);
    }


    /**
     * 转换为 toCommodityVO
     *
     * @param o Object
     * @return CommodityVO
     */
    private CommodityVO toCommodityVO(Object o) {
        Map map = (Map) o;
        JSONObject jsonObject = new JSONObject(map);
        JSONObject cartJson = jsonObject.getJSONObject("id");
        Integer shopId = cartJson.getInteger("shopId");
        String skuCode = cartJson.getString("skuCode");
        Integer number = jsonObject.getInteger("num");
        Long skuId = jsonObject.getLong("skuId");
        Long goodsId = jsonObject.getLong("goodsId");
        return toCommodityVO(shopId, skuCode, number, skuId, goodsId);
    }

    /**
     * 调用商品服务进行数据转换
     *
     * @param shopId
     * @param skuCode
     * @param number
     * @return
     */
    private CommodityVO toCommodityVO(Integer shopId, String skuCode, Integer number, Long skuId, Long goodsId) {
        JSONObject skuDetails = restTemplate.getForObject("http://goods-service/skus/details?skuCode={1}&shopId={2}", JSONObject.class, skuCode, shopId);
        String title = skuDetails.getJSONObject("goodsDTO").getString("title");
        String picture = skuDetails.getJSONObject("goodsDTO").getString("picture");
        String thumb = picture;
        String splitStr = ",";
        if (picture.contains(splitStr)) {
            thumb = picture.split(",")[0].trim();
        }
        JSONObject attr = skuDetails.getJSONObject("attributes");
        // 适配 这样做不好
        String standard = attr.getString("版本") + "/" + attr.getString("制式");
        String color = attr.getString("颜色");
        // TODO 此处单位是元还是分
        Double price = skuDetails.getDouble("price");
        return CommodityVO.builder().title(title).standard(standard).color(color).count(number).price(price).thumb(thumb).shopId(shopId).skuCode(skuCode).skuId(skuId).goodsId(goodsId).build();
    }

    /**
     * 转换为 CartVO
     *
     * @param entry Map.Entry<Integer, List<CommodityVO>>
     * @return CartVO
     */
    private CartVO toCartVO(Map.Entry<Integer, List<CommodityVO>> entry) {
        Integer shopId = entry.getKey();
        JSONObject shopJson = restTemplate.getForObject("http://merchant-service/merchants/shops/{1}", JSONObject.class, shopId);
        String shopName = shopJson.getJSONObject("shop").getString("name");
        return CartVO.builder().id(shopId).name(shopName).commodity(entry.getValue()).build();
    }

    /**
     * 生成订单数据归总
     */
    @PostMapping("/orderPage")
    public OrderReturnVo orderReturn(@RequestBody List<CartRequest> cartRequests) {
        ShippingAddress shippingAddress = getShippingAddress();
        List<OrderPageVo> list = getOrderSubmit(cartRequests);
        double totalPrice = 0;
        double totalFright = 0;
        Integer totalCount = 0;
        for (OrderPageVo orderSubmitVo : list) {
            totalPrice += orderSubmitVo.getAmount();
            totalFright += orderSubmitVo.getFreight();
            totalCount += orderSubmitVo.getTotalNum();
        }
        return OrderReturnVo.builder().address(shippingAddress).list(list).totalPrice(totalPrice).totalFreight(totalFright).totalCount(totalCount).payable(totalPrice + totalFright).build();
    }

    /**
     * 返回商品数据
     */
    private List<OrderPageVo> getOrderSubmit(List<CartRequest> cartRequests) {
        List<CartVO> cartVOList = cartRequests.stream().map(cartRequest -> this.toCommodityVO(cartRequest.getShopId(), cartRequest.getSkuCode(), cartRequest.getNumber(), cartRequest.getSkuId(), 0L))
                .collect(Collectors.groupingBy(CommodityVO::getShopId)).entrySet().stream()
                .map(this::toCartVO)
                .collect(Collectors.toList());
        List<OrderPageVo> list = new ArrayList<>();
        cartVOList.forEach(cartVO -> {
            Integer shopId = cartVO.getId();
            Integer totalNum = cartVO.getCommodity().stream().mapToInt(CommodityVO::getCount).sum();
            Double totalPrice = cartVO.getCommodity().stream().mapToDouble(commodityVO -> commodityVO.getPrice() * commodityVO.getCount()).sum();
            Double freight = getFreight(shopId, totalNum, totalPrice);
            list.add(new OrderPageVo(shopId, cartVO.getName(), cartVO.getCommodity(), totalPrice, freight, totalPrice + freight, totalNum));
        });
        return list;
    }

    private Double getFreight(Integer shopId, Integer totalNum, Double totalPrice) {
        FreightVo freightVo = restTemplate.getForObject("http://merchant-service/merchants/freight/" + shopId + "/one", FreightVo.class);
        Integer type = freightVo.getType();
        Double freight = 0D;
        switch (type) {
            case 0:
                freight = 0D;
                break;
            case 1:
                freight = freightVo.getCount() <= totalNum ? 0D : (freightVo.getPrice() / 100);
                break;
            case 2:
                freight = freightVo.getCount() <= totalPrice ? 0D : (freightVo.getPrice() / 100);
                break;
            case 3:
                freight = freightVo.getPrice() / 100;
                break;
            default:
        }
        return freight;
    }

    /**
     * 默认收货地
     */
    private ShippingAddress getShippingAddress() {
        Integer currentUserId = UserInfoManager.getCurrentUserId();
        JSONObject jsonObject = restTemplate.getForObject("http://user-service/users/receivingInformation/{1}/enabled", JSONObject.class, currentUserId);
        if (Objects.nonNull(jsonObject)) {
            return new ShippingAddress(
                    jsonObject.getInteger("id"),
                    jsonObject.getString("name"),
                    jsonObject.getBoolean("enabled"),
                    jsonObject.getString("mobile"),
                    jsonObject.getString("province") + "-" + jsonObject.getString("city") + "-" + jsonObject.getString("district"),
                    jsonObject.getString("road")
            );
        } else {
            return new ShippingAddress();
        }
    }


}
